package com.musicsonar.android.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xmlpull.v1.XmlSerializer;

import android.util.Xml;

import com.musicsonar.android.bean.PlayList;
import com.musicsonar.android.bean.Song;

public abstract class SongsManager {

	// SDCard Path
	final static String XML_FILE_NAME = new String("MusicSonar.PlayList.xml");
	public static Song actualSong;
	private static List<PlayList> playList = new ArrayList<PlayList>();

	public static List<PlayList> getPlayList(){
		if(playList.size() == 0){
			getActualPlayList();
		}
		return playList;
	}

	public static PlayList getPlayList(int index){
		if(playList.size() == 0){
			getActualPlayList();
		}
		return playList.get(index);
	}

	public static PlayList getActualPlayList(){
		File directory = new File(MusicSonarConstant.MEDIA_PATH);
		if(!directory.exists()){
			directory.mkdir();
		}
		File file = new File(MusicSonarConstant.MEDIA_PATH+XML_FILE_NAME);

		if(!file.exists()){
			savePlayList(getSelectedPlayList().getSongList());
		}

		if(playList.size() == 0){
			playList = readXML(file);
		}

		return getSelectedPlayList();
	}

	public static void selectPlayList(int index){
		for(PlayList pl : playList){
			pl.setActive(Boolean.FALSE);
		}
		playList.get(index).setActive(Boolean.TRUE);
		savePlayList(getActualPlayList().getSongList());
	}

	public static void deletePlayList(){
		playList.remove(getActualPlayList());
		if(playList.size() > 0){
			playList.get(0).setActive(Boolean.TRUE);
		}else{
			playList.add(getSelectedPlayList());
		}
		savePlayList(getActualPlayList().getSongList());
	}

	public static void createNewPlayList(String name){
		for(PlayList pl : playList){
			pl.setActive(Boolean.FALSE);
		}
		PlayList pl = new PlayList();
		pl.setCode(new Long(playList.size()));
		pl.setName(name);
		pl.setActive(Boolean.TRUE);
		pl.setSaved(Boolean.FALSE);
		playList.add(pl);
		savePlayList(pl.getSongList());
	}

	public static void editPlayList(String name){
		PlayList pl = getSelectedPlayList();
		pl.setName(name);
		savePlayList(pl.getSongList());
	}

	@SuppressWarnings("unchecked")
	public static void savePlayList(List<?> songsList){
		File directory = new File(MusicSonarConstant.MEDIA_PATH);
		if(!directory.exists()){
			directory.mkdir();
		}
		File file = new File(MusicSonarConstant.MEDIA_PATH+XML_FILE_NAME);
		List<Song> list = new ArrayList<Song>();
		if(songsList != null && songsList.size() > 0){
			if(songsList.get(0) instanceof Song){
				list = (List<Song>)songsList;
			}
			if(songsList.get(0) instanceof Map){
				List<Map<String, Object>> tmp = (List<Map<String, Object>>)songsList;
				for(Map<String, Object> item : tmp){
					Song song = new Song(item);
					list.add(song);
				}
			}
		}
		saveDocument(file, list);
	}

	private static boolean saveDocument(File file, List<Song> songsList){
		PlayList _playList = getSelectedPlayList();
		_playList.setSongList(songsList);
		for(PlayList pl : playList){
			if(pl.getCode().intValue() != _playList.getCode().intValue()){
				pl.setActive(Boolean.FALSE);
			}
		}
		return createXMLFile(file);
	}

	private static boolean createXMLFile(File file){
		XmlSerializer serializer = Xml.newSerializer();
		StringWriter writer = new StringWriter();
	    try {
	        serializer.setOutput(writer);
	        serializer.startDocument("UTF-8", true);
	        serializer.startTag("", "music-sonar");
	        for(PlayList _playList : playList){
		        serializer.startTag("", "songs-list");
		        serializer.attribute(null, "code", _playList.getCode().toString());
		        serializer.attribute(null, "name", _playList.getName());
		        serializer.attribute(null, "active", _playList.getActive().toString());
		        serializer.attribute(null, "saved", _playList.getSaved().toString());
		        for (Song item : _playList.getSongList()){
		        	serializer.startTag("", "song");
		        	/**/
		        		serializer.startTag("", "index");
		        		serializer.text(item.getIndex().toString());
		        		serializer.endTag("", "index");
		        	/**/

			        /**/
		        		serializer.startTag("", "songPath");
		        		serializer.text(item.getSongPath());
		        		serializer.endTag("", "songPath");
		        	/**/

			        /**/
		        		serializer.startTag("", "segundos");
		        		serializer.text(item.getSegundos().toString());
		        		serializer.endTag("", "segundos");
		        	/**/

			        /**/
		        		serializer.startTag("", "songImage");
		        		serializer.text(item.getSongImage());
		        		serializer.endTag("", "songImage");
		        	/**/

			        /**/
		        		serializer.startTag("", "songYT");
		        		serializer.text(item.getSongYT());
		        		serializer.endTag("", "songYT");
		        	/**/

		        	/**/
		        		serializer.startTag("", "songTitle");
		        		serializer.text(item.getSongTitle());
		        		serializer.endTag("", "songTitle");
		        	/**/

			        /**/
		        		serializer.startTag("", "songDuration");
		        		serializer.text(item.getSongDuration());
		        		serializer.endTag("", "songDuration");
		        	/**/
		        	serializer.endTag("", "song");
		        }
		        serializer.endTag("", "songs-list");
	        }
	        serializer.endTag("", "music-sonar");
	        serializer.endDocument();
	        FileOutputStream fos = new FileOutputStream(file);
	        fos.write(writer.toString().getBytes());
	        fos.flush();
	        fos.close();
	        return true;
	    } catch (Exception e) {
	        throw new RuntimeException(e);
	    }
	}

	private static List<PlayList> readXML(File file){
		List<PlayList> result = new ArrayList<PlayList>();
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		try{
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document dom = builder.parse(new FileInputStream(file));
			Element root = dom.getDocumentElement();
			NodeList bigTag = root.getElementsByTagName("songs-list");
			for(int i = 0; i < bigTag.getLength(); i++){
				Node big = bigTag.item(i);
				PlayList playList = new PlayList();
				NamedNodeMap attributes = big.getAttributes();
				if(attributes != null && attributes.getLength() > 0){
					Attr name = (Attr)attributes.getNamedItem("name");
					Attr code = (Attr)attributes.getNamedItem("code");
					Attr active = (Attr)attributes.getNamedItem("active");
					Attr saved = (Attr)attributes.getNamedItem("saved");
					playList.setCode(new Long(code.getValue()));
					playList.setName(name.getValue());
					playList.setActive("true".equalsIgnoreCase(active.getValue()));
					playList.setSaved("true".equalsIgnoreCase(saved != null ? saved.getValue() : "false"));
				}else{
					playList = getSelectedPlayList();
				}
				NodeList items = big.getChildNodes();
				for (int k = 0; k < items.getLength(); k++){
					HashMap<String, Object> data = new HashMap<String, Object>();
					Node item = items.item(k);
					NodeList information = item.getChildNodes();
					for(int j = 0; j < information.getLength(); j++){
						Node nodo = information.item(j);
						data.put(nodo.getNodeName(), nodo.getTextContent());
					}
					playList.getSongList().add(new Song(data));
				}
				result.add(playList);
			}
		} catch (Exception e){
			throw new RuntimeException(e);
		}
		return result;
	}

	private static PlayList getSelectedPlayList(){
		PlayList result = new PlayList();
		if(playList != null && playList.size() > 0){
			for(PlayList item : playList){
				if(item.getActive()){
					result = item;
					break;
				}
			}
		}else{
			result.setCode(new Long(playList.size()));
			result.setName("default");
			result.setActive(Boolean.TRUE);
			result.setSaved(Boolean.FALSE);
			playList.add(result);
		}
		return result;
	}
}